package com.starview.star.operators.arith.runtime;

import com.starview.platform.data.EvaluationException;
import com.starview.platform.data.IFunction;
import com.starview.platform.data.IValue;
import com.starview.platform.data.type.IType;
import com.starview.platform.data.type.StandardTypes;
import com.starview.platform.data.type.TypeUtils;
import com.starview.platform.data.value.Factory;
import com.starview.star.operators.CafeEnter;



/**
 * Binary arithmetic functions
 * 
 * @author fgm
 * 
 */

public abstract class LongBinary
{

  public static class LongPlus implements IFunction
  {
    @CafeEnter
    public static long enter(long s1, long s2)
    {
      return s1 + s2;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return Factory.newLng(enter(Factory.lngValue(args[0]), Factory.lngValue(args[1])));
    }

    @Override
    public IType getType()
    {
      IType longType = StandardTypes.rawLongType;
      return TypeUtils.functionType(longType, longType, longType);
    }
  }

  public static class LongMinus implements IFunction
  {
    @CafeEnter
    public static long enter(long s1, long s2)
    {
      return s1 - s2;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return Factory.newLng(enter(Factory.lngValue(args[0]), Factory.lngValue(args[1])));
    }

    @Override
    public IType getType()
    {
      IType longType = StandardTypes.rawLongType;
      return TypeUtils.functionType(longType, longType, longType);
    }
  }

  public static class LongTimes implements IFunction
  {
    @CafeEnter
    public static long enter(long s1, long s2)
    {
      return s1 * s2;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return Factory.newLng(enter(Factory.lngValue(args[0]), Factory.lngValue(args[1])));
    }

    @Override
    public IType getType()
    {
      IType longType = StandardTypes.rawLongType;
      return TypeUtils.functionType(longType, longType, longType);
    }
  }

  public static class LongDivide implements IFunction
  {
    @CafeEnter
    public static long enter(long s1, long s2)
    {
      return s1 / s2;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return Factory.newLng(enter(Factory.lngValue(args[0]), Factory.lngValue(args[1])));
    }

    @Override
    public IType getType()
    {
      IType longType = StandardTypes.rawLongType;
      return TypeUtils.functionType(longType, longType, longType);
    }
  }

  public static class LongRemainder implements IFunction
  {
    @CafeEnter
    public static long enter(long s1, long s2)
    {
      return s1 % s2;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return Factory.newLng(enter(Factory.lngValue(args[0]), Factory.lngValue(args[1])));
    }

    @Override
    public IType getType()
    {
      IType longType = StandardTypes.rawLongType;
      return TypeUtils.functionType(longType, longType, longType);
    }
  }

  public static class LongMin implements IFunction
  {
    @CafeEnter
    public static long enter(long s1, long s2)
    {
      return Math.min(s1, s2);
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return Factory.newLng(enter(Factory.lngValue(args[0]), Factory.lngValue(args[1])));
    }

    @Override
    public IType getType()
    {
      IType longType = StandardTypes.rawLongType;
      return TypeUtils.functionType(longType, longType, longType);
    }
  }

  public static class LongMax implements IFunction
  {
    @CafeEnter
    public static long enter(long s1, long s2)
    {
      return Math.max(s1, s2);
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return Factory.newLng(enter(Factory.lngValue(args[0]), Factory.lngValue(args[1])));
    }

    @Override
    public IType getType()
    {
      IType longType = StandardTypes.rawLongType;
      return TypeUtils.functionType(longType, longType, longType);
    }
  }

  public static class LongPwr implements IFunction
  {
    @CafeEnter
    public static long enter(long s1, long s2)
    {
      return (long) Math.pow(s1, s2);
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return Factory.newLng(enter(Factory.lngValue(args[0]), Factory.lngValue(args[1])));
    }

    @Override
    public IType getType()
    {
      IType longType = StandardTypes.rawLongType;
      return TypeUtils.functionType(longType, longType, longType);
    }
  }

  public static class LongLeft implements IFunction
  {
    @CafeEnter
    public static long enter(long s1, long s2)
    {
      return (long) s1 << s2;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return Factory.newLng(enter(Factory.lngValue(args[0]), Factory.lngValue(args[1])));
    }

    @Override
    public IType getType()
    {
      IType longType = StandardTypes.rawLongType;
      return TypeUtils.functionType(longType, longType, longType);
    }
  }

  public static class LongRight implements IFunction
  {
    @CafeEnter
    public static long enter(long s1, long s2)
    {
      return (long) s1 >> s2;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return Factory.newLng(enter(Factory.lngValue(args[0]), Factory.lngValue(args[1])));
    }

    @Override
    public IType getType()
    {
      IType longType = StandardTypes.rawLongType;
      return TypeUtils.functionType(longType, longType, longType);
    }
  }
}
